{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# K-Means Demo\n",
    "\n",
    "KMeans is a basic but powerful clustering method which is optimized via Expectation Maximization. It randomly selects K data points in X, and computes which samples are close to these points. For every cluster of points, a mean is computed, and this becomes the new centroid.\n",
    "\n",
    "cuML’s KMeans supports the scalable KMeans++ initialization method. This method is more stable than randomnly selecting K points.\n",
    "    \n",
    "The model can take array-like objects, either in host as NumPy arrays or in device (as Numba or cuda_array_interface-compliant), as well as cuDF DataFrames as the input.\n",
    "\n",
    "For information about cuDF, refer to the [cuDF documentation](https://docs.rapids.ai/api/cudf/stable).\n",
    "\n",
    "For additional information on cuML's k-means implementation: https://docs.rapids.ai/api/cuml/stable/api.html#cuml.KMeans."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cudf\n",
    "import cupy\n",
    "import matplotlib.pyplot as plt\n",
    "from cuml.cluster import KMeans as cuKMeans\n",
    "from cuml.datasets import make_blobs\n",
    "from sklearn.cluster import KMeans as skKMeans\n",
    "from sklearn.metrics import adjusted_rand_score\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define Parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_samples = 100000\n",
    "n_features = 25\n",
    "\n",
    "n_clusters = 8\n",
    "random_state = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generate Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "device_data, device_labels = make_blobs(\n",
    "    n_samples=n_samples,\n",
    "    n_features=n_features,\n",
    "    centers=n_clusters,\n",
    "    random_state=random_state,\n",
    "    cluster_std=0.1\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Copy CuPy arrays from GPU memory to host memory (NumPy arrays).\n",
    "# This is done to later compare CPU and GPU results.\n",
    "host_data = device_data.get()\n",
    "host_labels = device_labels.get()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scikit-learn model\n",
    "\n",
    "### Fit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "166 ms ± 9.18 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
     ]
    }
   ],
   "source": [
    "kmeans_sk = skKMeans(\n",
    "    init=\"k-means++\",\n",
    "    n_clusters=n_clusters,\n",
    "    random_state=random_state,\n",
    "    n_init='auto'\n",
    ")\n",
    "%timeit kmeans_sk.fit(host_data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## cuML Model\n",
    "\n",
    "### Fit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13.4 ms ± 37.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "kmeans_cuml = cuKMeans(\n",
    "    init=\"k-means||\",\n",
    "    n_clusters=n_clusters,\n",
    "    random_state=random_state\n",
    ")\n",
    "\n",
    "%timeit kmeans_cuml.fit(device_data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualize Centroids\n",
    "\n",
    "Scikit-learn's k-means implementation uses the `k-means++` initialization strategy while cuML's k-means uses `k-means||`. As a result, the exact centroids found may not be exact as the std deviation of the points around the centroids in `make_blobs` is increased.\n",
    "\n",
    "*Note*: This is visualizing the centroids in only two dimensions. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABQoAAANCCAYAAAAuhvFjAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAACHEUlEQVR4nOzdZ5hdZdk24GtNT5tJh4QkhN5C70gRpBdBBJEiIDZ8sWBBxILAq2Lhw/baCyAKWFBEpIsUFaR36S0QSCAkM6mTKev7AURiEpJJsmcn4TyPYw6dtdd67nv2ZBJy5SlFWZZlAAAAAIA3tZpqNwAAAAAAVJ+gEAAAAAAQFAIAAAAAgkIAAAAAIIJCAAAAACCCQgAAAAAggkIAAAAAIIJCAAAAACCCQgAAAAAggkIAYAm99a1vTVEUWXPNNVOW5Xyv33jjjSmKIkVR5Nxzz517/dxzz01RFLn99tt7sdueuf7661MURa6//vqlHuutb31rxo0bt8j7xo4dm2OPPXap61XDivA9XZ499dRT8/2cLEsTJkzIaaedlrvvvrsi47/2/X/qqacqMj4A0HsEhQDAEhswYECefPLJXHfddfO99otf/CLNzc1V6Ap4vQkTJuT000+vWFC433775eabb86IESMqMj4A0HsEhQDAEhszZky22267/OIXv5jn+rRp0/K73/0uhx12WJU6Y3HNnDmz2i2wgpo1a1bKssywYcOy3XbbpbGxsdotAQBLSVAIAG8iDz30UA4//PCsssoqaWxszJgxY3L00Uenvb09SXLaaaelKIr5nnujpYXHHXdc/vCHP2Tq1Klzr1100UVJkne/+93LtP/vf//72XnnnTN8+PD069cvG2+8cb7xjW+ko6NjnvteW+572223Zaeddkrfvn2z5ppr5mtf+1q6u7vnufehhx7K3nvvnb59+2bo0KE5/vjjM23atMXq58UXX8wHP/jBjB49Oo2NjRk2bFje8pa35Nprr33D5/74xz+mb9++ef/735/Ozs6F3tfW1pZPf/rTWWONNdLQ0JDVVlstJ554YmbMmLFU78uNN96YHXbYIX379s1xxx03d+nrWWedlbPPPjtrrLFG+vfvn+233z633HLLYr0X/+3555/PlltumXXWWSePPvpokuTYY49N//7989BDD2WvvfZKv379MmLEiHzta19Lktxyyy3Zcccd069fv6y77ro577zz5hv3hRdeyIc+9KGMGjUqDQ0NWWONNXL66afP9z6efvrp2XbbbTN48OA0Nzdniy22yM9//vP5lsmPHTs2+++/f6688spsscUW6dOnT9Zff/35wu+ZM2fO/V40NTVl8ODB2WqrrXLhhRcu8r147rnn5v46aWhoyMiRI3PIIYdk4sSJC33m2GOPzdixY+e7vqCf0d/97nfZdttt09LSMvfX+nHHHZfklWX0W2+9dZLkve9979ztAE477bS5z99+++15+9vfnsGDB6epqSmbb755fvvb385T47XfA66++uocd9xxGTZsWPr27Zv29vYF/v7Qk5/BBx54IHvuuWf69u2bYcOG5YQTTshf/vKXZbb8HwBYfHXVbgAA6B333HNPdtxxxwwdOjRnnHFG1llnnTz//PO59NJLM2fOnCWeDfTud787n/jEJ3LhhRfmwx/+cJLk5z//eQ455JBlvvT48ccfzxFHHDE3OLvnnnvyla98JQ899NB8wc4LL7yQI488Mp/61KfypS99KX/84x9zyimnZOTIkTn66KOTJBMnTswuu+yS+vr6/OAHP8gqq6ySX//61/nIRz6yWP285z3vyZ133pmvfOUrWXfddTN16tTceeedmTx58kKf+da3vpWTTjopp512Wr7whS8s9L6ZM2dml112ybPPPpvPfe5z2WSTTfLAAw/k1FNPzX333Zdrr712bmDUk/fl+eefz1FHHZXPfOYz+epXv5qamv/8u/H3v//9rL/++vn2t7+dJPniF7+YfffdN08++WRaWloW6z1Jkvvvvz/77rtvRo0alZtvvjlDhw6d+1pHR0cOPvjgHH/88TnppJNywQUX5JRTTklbW1suvvjinHzyyRk1alS+973v5dhjj824ceOy5ZZbJnnle7rNNtukpqYmp556atZaa63cfPPN+fKXv5ynnnoq55xzztw6Tz31VD70oQ9lzJgxSV4JIT/60Y/mueeey6mnnjpPv/fcc08+9alP5bOf/WxWWWWV/OxnP8v73ve+rL322tl5552TJJ/85Cdz/vnn58tf/nI233zzzJgxI/fff/8bfq+TV0LCrbfeOh0dHXO/j5MnT85VV12VKVOmZJVVVlns93VBbr755hx22GE57LDDctppp6WpqSlPP/303O0Atthii5xzzjl573vfmy984QvZb7/9kiSjRo1Kkvztb3/L3nvvnW233TY/+tGP0tLSkosuuiiHHXZYZs6cOd++mccdd1z222+/nH/++ZkxY0bq6+sX2tvi/Aw+//zz2WWXXdKvX7/88Ic/zPDhw3PhhRcu9s8gALCMlQDAm8Juu+1WDhw4sJw0adJC7/nSl75ULug/D84555wySfnkk0/OvbbLLruUG220UVmWZXnMMceUW221VVmWZfnAAw+UScrrr7++vO2228ok5TnnnDPfWLfddttSfT1dXV1lR0dH+ctf/rKsra0tX3755Xl6S1L+61//mueZDTfcsNxrr73mfn7yySeXRVGUd9999zz37bHHHmWS8m9/+9sb9tC/f//yxBNPfMN7Xnufurq6yo985CNlQ0ND+atf/Wq++1ZfffXymGOOmfv5mWeeWdbU1Mz3Pv3+978vk5SXX375Austzvvy17/+dZ5nnnzyyTJJufHGG5ednZ1zr996661lkvLCCy98w6/x9d/Ta665pmxubi4POeSQctasWfPcd8wxx5RJyosvvnjutY6OjnLYsGFlkvLOO++ce33y5MllbW1t+clPfnLutQ996ENl//79y6effnqecc8666wySfnAAw+84XtyxhlnlEOGDCm7u7vnvrb66quXTU1N84w5a9ascvDgweWHPvShudfGjRtXHnTQQW/4PizIcccdV9bX15cPPvjgQu957f1//c/JMcccU66++urz3fvfP6Ovfe1Tp05d6PgL+jl8zfrrr19uvvnmZUdHxzzX999//3LEiBFlV1dXWZb/+R4fffTR842xsN8fFudn8KSTTiqLopjve7fXXnst1s8gALBsWXoMAG8CM2fOzA033JB3vetdGTZs2DIf/7jjjsvtt9+e++67Lz//+c+z1lprzZ2JtSzdddddefvb354hQ4aktrY29fX1Ofroo9PV1ZVHHnlknntXXXXVbLPNNvNc22STTfL000/P/fxvf/tbNtpoo2y66abz3HfEEUcsVj/bbLNNzj333Hz5y1/OLbfcMt9S39fMnj07Bx10UH7961/n6quvzpFHHrnIsS+77LKMGzcum222WTo7O+d+7LXXXvMtyezJ+zJo0KDstttuC6y53377pba2du7nm2yySZLM8569kfPOOy/77rtv3v/+9+e3v/1tmpqa5runKIrsu+++cz+vq6vL2muvnREjRmTzzTefe33w4MEZPnz4PLUvu+yy7Lrrrhk5cuQ878k+++yTJLnhhhvm3nvddddl9913T0tLy9z35NRTT83kyZMzadKkeXrabLPN5s48TJKmpqasu+6689TeZpttcsUVV+Szn/1srr/++syaNWux3pMrrrgiu+66azbYYIPFur+nXltW/K53vSu//e1v89xzzy32s4899lgeeuihub8eX/+e7rvvvnn++efz8MMPz/PMO9/5zsUef3F+Bm+44YaMGzcuG2644Tz3HX744YtdBwBYdgSFAPAmMGXKlHR1dc1dbris7bzzzllnnXXy4x//OOeff36OO+64Be51uDSeeeaZ7LTTTnnuuefyne98JzfddFNuu+22fP/730+S+YKbIUOGzDdGY2PjPPdNnjw5q6666nz3LejagvzmN7/JMccck5/97GfZfvvtM3jw4Bx99NF54YUX5rlv0qRJueqqq7L99ttnhx12WKyxJ06cmHvvvTf19fXzfAwYMCBlWeall15K0vP35Y1Opv3v9+y15eiLG4pddNFF6dOnT97//vcv9Pvft2/f+QLEhoaGDB48eL57GxoaMnv27LmfT5w4MX/+85/ne0822mijJJn7ntx6663Zc889kyQ//elP849//CO33XZbPv/5zy/w61mcXyvf/e53c/LJJ+eSSy7JrrvumsGDB+eggw6au//iwrz44osV+7lLXvnZu+SSS9LZ2Zmjjz46o0aNyrhx4xZr78TX9kj89Kc/Pd97+j//8z9J/vOevqYnJxsv7s/ggpZfL+2SbABgydijEADeBAYPHpza2to8++yzb3jfawFOe3v7PHsW/ndYsCCv7YFWFEWOOeaYpWt4AS655JLMmDEjf/jDH7L66qvPvX733Xcv8ZhDhgyZL9RLssBrCzJ06NB8+9vfzre//e0888wzufTSS/PZz342kyZNypVXXjn3vjFjxuTss8/OO97xjhx88MH53e9+t8DZdv89dp8+febbY/D1ryc9f1+WdYD7er/+9a/zxS9+MbvsskuuvvrqbLbZZst0/KFDh2aTTTbJV77ylQW+PnLkyCSvBJb19fW57LLL5nmfL7nkkiWu3a9fv5x++uk5/fTTM3HixLmzCw844IA89NBDC31u2LBhi/y5W5Cmpqa5hwy93oJ+Fg888MAceOCBaW9vzy233JIzzzwzRxxxRMaOHZvtt99+oTVe+zV0yimn5OCDD17gPeutt948ny/rXz9DhgxZ4KEui/szCAAsW2YUAsCbQJ8+fbLLLrvkd7/73RuGfq+dsnrvvffOc/3Pf/7zImscc8wxOeCAA3LSSSdltdVWW6p+F+S1gOL1AWZZlvnpT3+6xGPuuuuueeCBB3LPPffMc/2CCy7o8VhjxozJRz7ykeyxxx65884753t9zz33zFVXXZUbb7wx+++//3wnF/+3/fffP48//niGDBmSrbbaar6P175XlXhfltTgwYNz7bXXZoMNNsiuu+66xCcmL8z++++f+++/P2uttdYC35PXgsKiKFJXVzfPMupZs2bl/PPPXyZ9rLLKKjn22GNz+OGH5+GHH87MmTMXeu8+++yTv/3tb/Mt4V2UsWPHZtKkSfOEaHPmzMlVV1210GcaGxuzyy675Otf/3qSV5akv3Y9mX8m5XrrrZd11lkn99xzzwLfz6222ioDBgzoUd89tcsuu+T+++/Pgw8+OM/1105OBwB6lxmFAPAmcfbZZ2fHHXfMtttum89+9rNZe+21M3HixFx66aX58Y9/nAEDBmTffffN4MGD8773vS9nnHFG6urqcu6552b8+PGLHH/kyJE9mrF13XXX5amnnprv+r777pu+ffvOd32PPfZIQ0NDDj/88HzmM5/J7Nmz88Mf/jBTpkxZ7Jr/7cQTT8wvfvGL7Lfffvnyl78899TjN5oh9prW1tbsuuuuOeKII7L++utnwIABue2223LllVcudHbWjjvumL/+9a/Ze++9s+eee+byyy9f6GnCJ554Yi6++OLsvPPO+cQnPpFNNtkk3d3deeaZZ3L11VfnU5/6VLbddtuKvC9LY8CAAXPfgz322COXXnppdt1112Uy9hlnnJFrrrkmO+ywQz72sY9lvfXWy+zZs/PUU0/l8ssvz49+9KOMGjUq++23X84+++wcccQR+eAHP5jJkyfnrLPOWuKTvZNk2223zf77759NNtkkgwYNyr///e+cf/752X777Rf46/X1PV9xxRXZeeed87nPfS4bb7xxpk6dmiuvvDKf/OQns/766y/wucMOOyynnnpq3v3ud+ekk07K7Nmz893vfjddXV3z3Hfqqafm2Wefzdve9raMGjUqU6dOzXe+853U19dnl112SZKstdZa6dOnT379619ngw02SP/+/TNy5MiMHDkyP/7xj7PPPvtkr732yrHHHpvVVlstL7/8cv7973/nzjvvzO9+97slfs8Wx2s/g/vss0/OOOOMrLLKKrngggvm/gy+/lRuAKDy/MkLAG8Sm266aW699dZsueWWOeWUU7L33nvn5JNPTmNjYxoaGpIkzc3NufLKKzNgwIAcddRROf744zNu3Li5e7stSyeffHIOPfTQ+T7++6CJ16y//vq5+OKLM2XKlBx88MH56Ec/ms022yzf/e53l7iHVVddNTfccEM23HDDfPjDH85RRx2Vpqam/N///d8in21qasq2226b888/P0ceeWT22Wef/OxnP8vJJ5/8hrP5ttpqq9xwww154oknsttuuy10hme/fv1y00035dhjj81PfvKT7LfffnnXu96V7373uxk1atTcGYWVeF+WVp8+ffKnP/0pe+21V/bdd99cfvnly2TcESNG5Pbbb8+ee+6Zb37zm9l7773znve8J7/4xS+y2WabZdCgQUmS3XbbLb/4xS9y33335YADDsjnP//5HHLIIfnsZz+7xLV32223XHrppXnve9+bPffcM9/4xjdy9NFHL3K27WqrrZZbb701+++/f772ta9l7733zkc/+tG0trYucF/G16yxxhr505/+lKlTp+aQQw7JSSedlEMPPTRHH330PPdtu+22eeGFF3LyySdnzz33zAc/+MH06dMn11133dy9G/v27Ztf/OIXmTx5cvbcc89svfXW+clPfpLklVm1t956awYOHJgTTzwxu+++ez784Q/n2muvze67777E79fiGjlyZG644Yasu+66Of7443PkkUemoaEhZ5xxRpJk4MCBFe8BAPiPoizLstpNAAAAvOaDH/xgLrzwwkyePHnuP2QAAJVn6TEAAFA1Z5xxRkaOHJk111wz06dPz2WXXZaf/exn+cIXviAkBIBeJigEAACqpr6+Pt/85jfz7LPPprOzM+uss07OPvvsfPzjH692awDwpmPpMQAAAADgMBMAAAAAQFAIAAAAAERQCAAAAABkOT/MpLu7OxMmTMiAAQNSFEW12wEAAACAFUpZlpk2bVpGjhyZmpo3njO4XAeFEyZMyOjRo6vdBgAAAACs0MaPH59Ro0a94T3LdVA4YMCAJK98Ic3NzVXuBgAAAABWLG1tbRk9evTcnO2NLNdB4WvLjZubmwWFAAAAALCEFmdbP4eZAAAAAACCQgAA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ACCCQgAAAAAggkIAAAAAIIJCAAAAACCCQgAAAAAggkIAAAAAIIJCAAAAACCCQgAAAAAggkIAAAAAIIJCAAAAACCCQgAAAAAggkIAAAAAIIJCAAAAACCCQgAAAAAgvRAUPvfccznqqKMyZMiQ9O3bN5tttlnuuOOOSpcFAAAAAHqgrpKDT5kyJW95y1uy66675oorrsjw4cPz+OOPZ+DAgZUsCwAAAAD0UEWDwq9//esZPXp0zjnnnLnXxo4dW8mSAAAAAMASqOjS40svvTRbbbVVDj300AwfPjybb755fvrTn1ayJAAAAACwBCoaFD7xxBP54Q9/mHXWWSdXXXVVjj/++HzsYx/LL3/5ywXe397enra2tnk+AAAAAIDKK8qyLCs1eENDQ7baaqv885//nHvtYx/7WG677bbcfPPN891/2mmn5fTTT5/vemtra5qbmyvVJgAAAACslNra2tLS0rJY+VpFZxSOGDEiG2644TzXNthggzzzzDMLvP+UU05Ja2vr3I/x48dXsj0AAAAA4FUVPczkLW95Sx5++OF5rj3yyCNZffXVF3h/Y2NjGhsbK9kSAAAAALAAFZ1R+IlPfCK33HJLvvrVr+axxx7LBRdckJ/85Cc54YQTKlkWAAAAAOihigaFW2+9df74xz/mwgsvzLhx4/K///u/+fa3v50jjzyykmUBAAAAgB6q6GEmS6snmy0CAAAAAPNabg4zAQAAAABWDIJCAAAAAEBQCAAAAAAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgAgKAQAAAIAICgEAAACACAoBAAAAgPRiUHjmmWemKIqceOKJvVUSAAAAAFhMvRIU3nbbbfnJT36STTbZpDfKAQAAAAA9VPGgcPr06TnyyCPz05/+NIMGDap0OQAAAABgCVQ8KDzhhBOy3377Zffdd690KQAAAABgCdVVcvCLLrood955Z2677bbFur+9vT3t7e1zP29ra6tUawAAAADA61RsRuH48ePz8Y9/PL/61a/S1NS0WM+ceeaZaWlpmfsxevToSrUHAAAAALxOUZZlWYmBL7nkkrzjHe9IbW3t3GtdXV0piiI1NTVpb2+f57VkwTMKR48endbW1jQ3N1eiTQAAAABYabW1taWlpWWx8rWKLT1+29velvvuu2+ea+9973uz/vrr5+STT54vJEySxsbGNDY2VqolAAAAAGAhKhYUDhgwIOPGjZvnWr9+/TJkyJD5rgMAAAAA1VXxU48BAAAAgOVfRU89/m/XX399b5YDAAAAABaTGYUAAAAAgKAQAAAAABAUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAAABEUAgAAAAARFAIAAAAAERQCAAAA9Lquru7MnjUnZVlWuxWYq67aDQAAAAC8Wdx7x1P54wU355YbH053d5nGpvpstOmYbLHdmtli27Wy5rqrpiiKxR6vo6MzHXO60qdvQ4+egwUpyuU4um5ra0tLS0taW1vT3Nxc7XYAAAAAltgFP78h5/3gutTW1qSrq3uB9xRFkW13Wjdb7bB2/nXjw3nk3xOSJGPWGJajPvDWbLbNminLMn+/7t/500W35L47n06SDGjpk30P3ioHHrZNhgyTofAfPcnXBIUAAAAAFXbTXx/M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QPUJCgEAAAAAQSEAAAAAICgEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAABSwaDwqaeeyvve976sscYa6dOnT9Zaa6186Utfypw5cypVEgAAAABYQnWVGvihhx5Kd3d3fvzjH2fttdfO/fffnw984AOZMWNGzjrrrEqVBQAAAACWQFGWZdlbxb75zW/mhz/8YZ544onFur+trS0tLS1pbW1Nc3NzhbsDAAAAgJVLT/K1is0oXJDW1tYMHjx4oa+3t7envb197udtbW290RYAAAAAvOn12mEmjz/+eL73ve/l+OOPX+g9Z555ZlpaWuZ+jB49urfaAwAAAIA3tR4HhaeddlqKonjDj9tvv32eZyZMmJC99947hx56aN7//vcvdOxTTjklra2tcz/Gjx/f868IAAAAAOixHu9R+NJLL+Wll156w3vGjh2bpqamJK+EhLvuumu23XbbnHvuuampWfxs0h6FAAAAALDkKrpH4dChQzN06NDFuve5557Lrrvumi233DLnnHNOj0JCAAAAAKD3VOwwkwkTJuStb31rxowZk7POOisvvvji3NdWXXXVSpUFAAAAAJZAxYLCq6++Oo899lgee+yxjBo1ap7XerjaGQAAAACosIqtBT722GNTluUCPwAAAACA5YtNAwEAAAAAQSEAAAAAICgEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAAAAAiKAQAAAAAIigEAAAAACIoBAAA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\n",
      "text/plain": [
       "<Figure size 1600x1000 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(16, 10))\n",
    "plt.scatter(host_data[:, 0], host_data[:, 1], c=host_labels, s=50, cmap='viridis')\n",
    "\n",
    "#plot the sklearn kmeans centers with blue filled circles\n",
    "centers_sk = kmeans_sk.cluster_centers_\n",
    "plt.scatter(centers_sk[:,0], centers_sk[:,1], c='blue', s=100, alpha=.5)\n",
    "\n",
    "#plot the cuml kmeans centers with red circle outlines\n",
    "centers_cuml = kmeans_cuml.cluster_centers_\n",
    "plt.scatter(cupy.asnumpy(centers_cuml[:, 0]), \n",
    "            cupy.asnumpy(centers_cuml[:, 1]), \n",
    "            facecolors = 'none', edgecolors='red', s=100)\n",
    "\n",
    "plt.title('cuML and sklearn kmeans clustering')\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Compare Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 41.3 ms, sys: 464 µs, total: 41.8 ms\n",
      "Wall time: 41 ms\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "cuml_score = adjusted_rand_score(host_labels, kmeans_cuml.labels_.get())\n",
    "sk_score = adjusted_rand_score(host_labels, kmeans_sk.labels_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "compare kmeans: cuml vs sklearn labels_ are equal\n"
     ]
    }
   ],
   "source": [
    "threshold = 1e-4\n",
    "\n",
    "passed = (cuml_score - sk_score) < threshold\n",
    "print('compare kmeans: cuml vs sklearn labels_ are ' + ('equal' if passed else 'NOT equal'))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
